/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package proyecto;

/**
 *
 * @author Luis Romero
 */
import java.util.logging.Level;
import java.util.logging.Logger;
import static proyecto.Constantes.*;

public class EX extends Thread {

    SharedMem MInt;
    Mem SIG;
    ID ANT;
    boolean repite;
    final Object lock;
    Nucleo N;
    Reloj reloj;

    EX() {
        MInt = new SharedMem();
        this.setName("EX");
        repite = true;
        lock = new Object();
    }

    public void setEtapas(Mem m, ID e) {
        ANT = e;
        SIG = m;
    }

    public void parar() {
        synchronized (lock) {
            try {
               // System.out.println("Parar Ex");
                lock.wait();
            } catch (InterruptedException ex) {
                Logger.getLogger(ID.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public void seguir() {
        synchronized (lock) {
          //  System.out.println("Seguir EX");
            lock.notify();
        }
    }
    
    public void setReloj(Reloj reloj){
        this.reloj = reloj;
    }

    public void setNucleo(Nucleo n){
        N=n;
    }

    public void run() {
        /*Determinar el tipo de operacion
         *SI requiere aritmetica se realiza la aritmetica
         *Se colocan los resultados
         * Se da orden de inicio al siguiente hilo
         */
        System.out.println("Inicio EX");
        N.seguir();
        this.parar();
        while (repite) {
            //N.seguir();
            //this.parar();
            int resultado;
            System.out.println("Ex: "+MInt.getReg(INST)+MInt.getReg(REGF1)+MInt.getReg(REGF2)+MInt.getReg(REGD));
            SIG.MInt.setReg(INST, MInt.getReg(INST));
            SIG.MInt.setReg(REGD, MInt.getReg(REGD));
            SIG.MInt.setReg(REGF1, MInt.getReg(REGF1));
            SIG.MInt.setReg(REGF2, MInt.getReg(REGF2));
            switch (MInt.getReg(INST)) {
                case DADDI:
                    resultado = MInt.getReg(REGA) + MInt.getReg(REGIMM);
                    MInt.setReg(ALUOUT, resultado);
                    break;
                case DADD:
                    resultado = MInt.getReg(REGA) + MInt.getReg(REGB);
                    MInt.setReg(ALUOUT, resultado);
                    break;
                case DSUB:
                    resultado = MInt.getReg(REGA) - MInt.getReg(REGB);
                    MInt.setReg(ALUOUT, resultado);
                    break;
                case DMUL:
                    resultado = MInt.getReg(REGA) * MInt.getReg(REGB);
                    MInt.setReg(ALUOUT, resultado);
                    break;
                case DDIV:
                    resultado = MInt.getReg(REGA) / MInt.getReg(REGB);
                    MInt.setReg(ALUOUT, resultado);
                    break;
                case LW:
                    resultado = MInt.getReg(REGA) + MInt.getReg(REGIMM);
                    MInt.setReg(ALUOUT, resultado);
                    break;
                case SW:
                    resultado = MInt.getReg(REGA) + MInt.getReg(REGIMM);
                    SIG.MInt.setReg(REGB, MInt.getReg(REGB));
                    MInt.setReg(ALUOUT, resultado);
                    break;
                case LL:
                    resultado = MInt.getReg(REGA) + MInt.getReg(REGIMM);
                    MInt.setReg(ALUOUT, resultado);
                    break;
                case SC:
                    resultado = MInt.getReg(REGA) + MInt.getReg(REGIMM);
                    SIG.MInt.setReg(REGB, MInt.getReg(REGB));
                    MInt.setReg(ALUOUT, resultado);
                    break;
                case FIN:
                    repite = false;
                    break;
                case INTERRUPT:
                    SIG.MInt.setReg(INST, INTERRUPT);
                    SIG.MInt.setReg(NPC, MInt.getReg(NPC));
                    repite = false;
                    break;
                default:
                    break;
            }
            
            reloj.cuentaHilo(2);
            reloj.seguir();
            
            SIG.MInt.setReg(ALUOUT, MInt.getReg(ALUOUT));
            SIG.seguir();
            this.parar();
            ANT.seguir();
            this.parar();
            if(!repite){
                SIG.seguir();
            }
           // SIG.seguir();
        }
       // this.seguir();
        System.out.println("Murio EX");
    }
}
